dojo.provide("lotex.html.Html");

dojo.require("dojo.lang.declare");
dojo.require("dojo.collections.ArrayList");
dojo.require("dojo.collections.Dictionary");
dojo.require("dojo.string.extras");
//dojo.require("lotex.Assert");
//TODO 实现一个可调试的arraylist&dictionary;
//     dojo的版本无法在Firebug中查看
dojo.getObject("lotex.html.ClassMapping",true);
(function() {
    var cm = new dojo.collections.Dictionary();
    cm.add("html","lotex.html.Html");
    cm.add("select","lotex.html.Select");
    cm.add("textbox","lotex.html.Input");
    cm.add("label","lotex.html.Label");
    cm.add("option","lotex.html.Option");
    lotex.html.ClassMapping = cm;
})();

dojo.declare("lotex.html.Html", null,
    function() {
        this.children = new dojo.collections.ArrayList();
        this.properties = new dojo.collections.Dictionary();
    },
{
    tag: 'html',
    validProperties: ["name","action"],
    innerHtmlNode: null,
    onLoadChild: null,
    setter: null,

    getFromJson: function(json,key) {
        return dj_undef(key, json) ? null : json[key];
    },
    loadFromJson: function(json) {
        var type = dj_undef("type", json) ? this.tag : json["type"];
        var el;
        if(type == this.tag) el = this;
        else {
            type = type.toLowerCase();
            el = dj_eval('new ' + lotex.html.ClassMapping.item(type));
        }

        if(el.setter!=null)el.setter(json);

        // FIXME option 没有执行loadFromJson
        for(var i=0;i<el.validProperties.length;i++){
            var property = el.validProperties[i];
            if(!dj_undef(property, json))
                el.setProp(property, json[property]);
        }
        if(el.innerHtmlNode!=null & !dj_undef(el.innerHtmlNode, json)) {
            el.add(json[el.innerHtmlNode]);
        }
        el.loadChild(json);
        // 当子节点加载完成后调用。
        if(el.onLoadChild!=null)el.onLoadChild();

        return el;
    },

    loadChild: function(json) {
        if(!dj_undef("children", json)) {
            for(var i=0;i<json["children"].length;i++){
                var c = json["children"][i];
                var child = new lotex.html.Input().loadFromJson(c);
                this.add(child);
                //if(c.type)
            }
        }
    },

    add: function(element) {
        this.children.add(element);
        return this;
    },
    addAll: function(elements) {
        this.children.addRange(elements);
        return this;
    },
    // 转义 v 中的 双引号等
    set: function(k, v) {
        this[k] = v;
        return this;
    },
    get: function(k) {
        return dj_undef(k, this) ? null : this[k];
    },

    setProp: function(k, v) {
        this.properties.add(k, v);
        return this;
    },
    getProp: function(k) {
        return this.properties.item(k);
    },
    toHtml: function() {
        var sb = [];
        sb.push(this.startTag());
        this.children.forEach(function(child) {
            if(child instanceof lotex.html.Html)
                sb.push(child.toHtml());
            else
                sb.push(child);
        });
        sb.push(this.endTag());
        return sb.join('');
    },

    startTag: function() {
        var sb = [];
        sb.push('<' + this.tag);
        this.properties.forEach(function(property) {
            sb.push(' ' + property.key + '="' + property.value + '"');
        });
        sb.push('>');
        return sb.join('');
    },
    endTag: function() {
        return '</' + this.tag + '>';
    }
});

dojo.declare("lotex.html.Form", lotex.html.Html, null, {
    tag: 'form',
    validProperties: ["name","action","id"],
    setter: function(json) {
        this.set('name', this.getFromJson(json,'name'));
    },
    loadChild: function(json) {
        // TODO 根据表单样式选择子元素加载方式
        this.loadChildStyle2(json);
    },
    loadChildStyle1: function(json) {
        if(!dj_undef("children", json)) {
            for(var i=0;i<json["children"].length;i++){
                var c = json["children"][i];
                var child = new lotex.html.Input().loadFromJson(c);
                var caption = child.get('label')!=null ?
                    child.get('label') : '';
                var label = new lotex.html.Label().add(caption).add(child);
                this.add(label);
                //if(c.type)
            }
        }
    },
    loadChildStyle2: function(json) {
        this.add('<ul id="formFields">');
        if(!dj_undef("children", json)) {
            for(var i=0;i<json["children"].length;i++){
                var c = json["children"][i];
                var child = new lotex.html.Input().loadFromJson(c);
                var caption = child.get('label')!=null ?
                    child.get('label') : '';
                var label = new lotex.html.Label().add(caption);
                this.add('<li class="">');
                this.add(label);
                this.add('<div>');
                this.add(child);
                this.add('</div>');
                this.add('</li>');
            }
        }
        this.add('<li class="buttons"><div>');
        this.add(new lotex.html.Button().setProp('class','btTxt')
            .setProp('name','save').setProp('value','Save')
            .setProp('onclick','lotex.Forms.get(\''
            +this.getProp('name')+'\').submit()'));
        this.add('</div></li>');

        this.add('</ul>');
    }

});

dojo.declare("lotex.html.Select", lotex.html.Html, null, {
    tag: 'select',
    setter: function(json) {
        this.set('label', this.getFromJson(json,'label'));
        this.set('value', this.getFromJson(json,'value'));
        this.set('dataUri', this.getFromJson(json,'dataUri'));
    },
    loadChild: function(json) {
        var dataUri = this.get("dataUri");
        if(dataUri == null) {
            lotex.html.Select.superclass.loadChild.apply(this, arguments);
            return;
        }
        var self = this;
        lotex.io.json({
            sync: true,
            url: lotexConfig.baseurl + dataUri,
            load: function(type, data, evt) {
                for(var i=0;i<data.length;i++) {
                    self.add(new lotex.html.Option().loadFromJson(data[i]));
                }
                //self.onLoadChild();
                d(self.toHtml());
            }
        });
    },
    onLoadChild: function() {
        var self = this;
        this.children.forEach(function(child) {
            if(child instanceof lotex.html.Option)
                if(child.getProp("value") == self.value)
                    child.setSelected();
        });
    }
});

dojo.declare("lotex.html.Input", lotex.html.Html, null, {
    tag: 'input',
    validProperties: ["name","value","id"],
    setter: function(json) {
        this.set('label', this.getFromJson(json,'label'));
    },
    __toHtml: function() {
        var html = lotex.html.Input.superclass.toHtml.apply(this, arguments);
        if(this.get('label')!=null) {
            var element = new lotex.html.Label();
            element.add(this.get('label'));
            element.add(html);
            return element.toHtml();
        } else
            return html;
    }
});

dojo.declare("lotex.html.Label", lotex.html.Html, null, {
    tag: 'label'
});

dojo.declare("lotex.html.Option", lotex.html.Html, null, {
    tag: 'option',
    validProperties: ["value","selected"],
    innerHtmlNode: 'name',
    setSelected: function() {
        this.setProp("selected", "selected");
    }
});

dojo.declare("lotex.html.Button", lotex.html.Html,
    function() {
        this.setProp('type','button');
    }
, {
    tag: 'input'
});
